// Copyright (C) joyinter
// All rights reserved.
// 
// Author : Jiang Li
// Date   : 2004-8-30

#include "stdafx.h"
#include "socklistener.h"
#include "socktool.h"

//##ModelId=44C4B5F6013C
CJoySockListener::CJoySockListener(void)
{
    m_hListenThread = NULL;
}

//##ModelId=44C4B5F60148
CJoySockListener::~CJoySockListener(void)
{
    Stop();
}

//##ModelId=44C4B5F6014B
bool CJoySockListener::Start(int nPort)
{
    sockaddr_in addr;
    MakeAddress(addr, NULL, nPort);
    if(!Create(SOCK_STREAM, addr, false, false))
    {
        return true;
    }

    m_data->AddRef();
    listen(m_data->m_hSocket, SOMAXCONN);
    g_sockTool.CreateThread(CJoySocketTool::sListenThreadProc, m_data);

    return true;
}

//##ModelId=44C4B5F6014D
void CJoySockListener::Stop()
{
    SOCKET s = INVALID_SOCKET;
    if(m_data != NULL)
    {
        s = m_data->m_hSocket;
    }

    Close();

    if(s != INVALID_SOCKET)
    {
        closesocket(s);
    }

    if(m_hListenThread != NULL)
    {
        CloseHandle(m_hListenThread);
    }
}

//##ModelId=44C4B5F60139
void CJoySockListener::OnAccept(CJoySockData* sockData)
{
    sockData;
}

//##ModelId=44C4B5F60030
DWORD WINAPI CJoySocketTool::sListenThreadProc(void* pContext)
{
    return g_sockTool.ListenThreadProc(pContext);
}
// do listen.

/*
static int CALLBACK LisConditionProc(
    IN LPWSABUF lpCallerId,
    IN LPWSABUF lpCallerData,
    IN OUT LPQOS lpSQOS,
    IN OUT LPQOS lpGQOS,
    IN LPWSABUF lpCalleeId,
    OUT LPWSABUF lpCalleeData,
    OUT GROUP FAR *g,
    IN DWORD_PTR dwCallbackData
)
{
    lpCallerId;
    lpCallerData;
    lpSQOS;
    lpGQOS;
    lpCalleeId;
    lpCalleeData;
    g;
    dwCallbackData;

    CJoySockAccept* accData = (CJoySockAccept*)dwCallbackData;

    if(lpCallerData == NULL)
    {
        return CF_ACCEPT;
    }
    int s = lpCallerData->len;
    if(s == 0)
    {
        return CF_ACCEPT;
    }

    accData->m_callerData       = new BYTE[s];
    memcpy(accData->m_callerData, lpCallerData->buf, s);
    accData->m_callerDataSize   = s;

    return CF_ACCEPT;
}
*/
//##ModelId=44C4B5F6002E
DWORD CJoySocketTool::ListenThreadProc(void*pContext)
{
    CJoySockData* sockData = (CJoySockData*)pContext;
    
    //listen(sockData->m_hSocket, SOMAXCONN);
    while(!sockData->m_bClose)
    {
        int c = 0;
        do
        {
		    fd_set fd;
		    FD_ZERO(&fd);
		    FD_SET(sockData->m_hSocket,&fd);
		    timeval tv;
		    tv.tv_sec=0;
            tv.tv_usec = this->m_timeOut;
		    c = select(0,&fd,NULL,NULL,&tv);
        }
        while(!sockData->m_bClose && c == 0);

        if(c == SOCKET_ERROR)
        {
            sockData->PostClose();
            break;
        }

        if(!sockData->m_bClose)
        {
            //CJoySockAccept* accData = new CJoySockAccept();
            //SOCKET s = WSAAccept(sockData->m_hSocket, NULL, NULL, LisConditionProc, (DWORD_PTR)accData);
            SOCKET s = accept(sockData->m_hSocket, NULL, NULL);
            if(s == INVALID_SOCKET)
            {
                continue;
            }
            CJoySockData* pData = sockData->CreateData(s);
            if(pData == NULL)
            {
                continue;
            }
            pData->m_bConnected = true;
            sockData->AddRef();
            //accData->m_data = pData;
            //PostAsyMessage(SAM_ACCEPT, (WPARAM)sockData, (LPARAM)accData);
            PostAsyMessage(SAM_ACCEPT, (WPARAM)sockData, (LPARAM)pData);
        }
        else
        {
            break;
        }
    }

    sockData->Release();
    return 0;
}

